package similarity;

import java.util.HashMap;

import lastfm.LastfmDataset;

public class UserSimalarityCalculation {
	
	public void calcSimilarity() {
		LastfmDataset lastfm = new LastfmDataset();
		
		int[] users = lastfm.getUserList();
		//int[] trackAveragePlaycounts = lastfm.getTracksAveragePlaycounts();
		
		int[] usersAveragePlaycounts = lastfm.getUsersAveragePlaycounts();
		
		for (int i = 0; i < users.length-1; i++) {
			HashMap<Integer,Integer> userTracks = lastfm.getUserTracks(users[i]);
			Integer [] firstUserTracks = new Integer[userTracks.size()];
			userTracks.keySet().toArray(firstUserTracks);
			
			for(int j = i+1; j < users.length; j++) {
				HashMap<Integer,Integer> relatedUserTracks = lastfm.getUserTracks(users[j]);
				double sim = 
					calcUserAverageSimilarity(userTracks, firstUserTracks, relatedUserTracks, 
							usersAveragePlaycounts[i], usersAveragePlaycounts[j]);
				
				lastfm.insertUsersSimilarity(i, j, sim, "user-based 16.03.2012");
			}
		}
	}

	public double calcItemAverageSimilarity(HashMap<Integer,Integer> userTracks,
			Integer[] firstUserTracks, 
			HashMap<Integer,Integer> relatedUserTracks, 
			int[] averagePlaycounts) {
		double similarity = 0.0;
		int numerator = 0;
		int denominator1 = 0;
		int denominator2 = 0;
		for (int trackId : firstUserTracks) {
			if(relatedUserTracks.containsKey(trackId)) {
				int firstUserRating = userTracks.get(trackId)- averagePlaycounts[trackId];
				int secondUserRating = relatedUserTracks.get(trackId) - averagePlaycounts[trackId];
				numerator += firstUserRating * secondUserRating;
				denominator1 += firstUserRating * firstUserRating;
				denominator2 += secondUserRating* secondUserRating;
			}
		}
		
		if(numerator == 0)
			return 0.0;
		
		similarity = ((double)numerator);
		similarity /= Math.sqrt((double) denominator1);
		similarity /= Math.sqrt((double) denominator2);

		return similarity;
	}

	public double calcUserAverageSimilarity(HashMap<Integer,Integer> userTracks,
			Integer[] firstUserTracks, 
			HashMap<Integer,Integer> relatedUserTracks, 
			int averagePlaycount1, int averagePlaycount2) {
		double similarity = 0.0;
		int numerator = 0;
		int denominator1 = 0;
		int denominator2 = 0;
		for (int trackId : firstUserTracks) {
			if(relatedUserTracks.containsKey(trackId)) {
				int firstUserRating = userTracks.get(trackId)- averagePlaycount1;
				int secondUserRating = relatedUserTracks.get(trackId) - averagePlaycount2;
				numerator += firstUserRating * secondUserRating;
				denominator1 += firstUserRating * firstUserRating;
				denominator2 += secondUserRating* secondUserRating;
			}
		}
		
		if(numerator == 0)
			return 0.0;
		
		similarity = ((double)numerator);
		similarity /= Math.sqrt((double) denominator1);
		similarity /= Math.sqrt((double) denominator2);

		return similarity;
	}
}
